﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using SvgNet.SvgGdi;

namespace Graphix
{
    public static class StaticHelpers
    {
        public const string Hour = "ʰ";
        public const string Minute = "ᵐ";
        public const string Degree = "°";
        public const string Degreeminute = "′";

        public static string[] GenerateFullDegrees(int start, int end, int tick)
        {
            start -= tick;
            int max = (end - start)/tick;
            string[] returned = new string[max];
            for (int i = 0; i < max; i++)
            {
                returned[i] = string.Format("{0}°", start += tick);
            }
            return returned;
        }

        public static string BuildHour(string hours, string minutes)
        {
            return string.Format("{0}{1}{2}{3}", hours, Hour, minutes, Minute);
        }

        public static string BuildHour(short hours, short minutes)
        {
            return string.Format("{0}{1}{2}{3}", hours, Hour, minutes, Minute);
        }

        public static IEnumerable<Enum> GetFlags(this Enum input)
        {
            foreach (Enum value in Enum.GetValues(input.GetType()))
            {
                if (input.HasFlag(value))
                {
                    yield return value;
                }
            }
        }

        private static byte[][] GetRGB(Bitmap bmp)
        {
            BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            IntPtr ptr = bmpData.Scan0;
            int numPixels = bmp.Width * bmp.Height, numBytes = bmpData.Stride * bmp.Height, padding = bmpData.Stride - bmp.Width * 3, i = 0, ct = 1;
            byte[] r = new byte[numPixels], g = new byte[numPixels], b = new byte[numPixels], rgb = new byte[numBytes];
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgb, 0, numBytes);

            for (int x = 0; x < numBytes - 3; x += 3)
            {
                if (x == (bmpData.Stride * ct - padding)) { x += padding; ct++; };
                r[i] = rgb[x]; g[i] = rgb[x + 1]; b[i] = rgb[x + 2]; i++;
            }
            bmp.UnlockBits(bmpData);
            return new byte[3][] { r, g, b };
        }

        public static Image AutoCrop(Bitmap bmp, Color color)
        {
            short r = color.R;
            short g = color.G;
            short b = color.B;

            byte[][] pixels = GetRGB(bmp);

            int h = bmp.Height - 1, w = bmp.Width, top = 0, bottom = h, left = bmp.Width, right = 0, white = 0;

            bool prevColor = false;
            for (int i = 0; i < pixels[0].Length; i++)
            {
                int x = (i % (w)), y = (int)(Math.Floor((decimal)(i / w)));
                if (pixels[0][i] == b && pixels[1][i] == g && pixels[2][i] == r) { white++; right = (x > right && white == 1) ? x : right; }
                else { left = (x < left && white >= 1) ? x : left; right = (x == w - 1 && white == 0) ? w - 1 : right; white = 0; }
                if (white == w) { top = (y - top < 3) ? y : top; bottom = (prevColor && x == w - 1 && y > top + 1) ? y : bottom; }
                left = (x == 0 && white == 0) ? 0 : left; bottom = (y == h && x == w - 1 && white != w && prevColor) ? h + 1 : bottom;
                if (x == w - 1) { prevColor = (white < w); white = 0; }
            }
            right = (right == 0) ? w : right; left = (left == w) ? 0 : left;

            //Crop the image
            Bitmap bmpCrop = bmp.Clone(new Rectangle(left, top, right - left + 1, bottom - top), bmp.PixelFormat);

            return bmpCrop;
        }

        public static void DrawTriangle(this IGraphics graphics, PointF center, float width, Color color)
        {
            //Point[] points = { new Point(10, 10), new Point(100, 10), new Point(50, 100) };
            //graphics.DrawPolygon(new Pen(Color.Blue), points);
            PointF[] points2 =
                {
                    new PointF(center.X - 0.5f*width, center.Y + ((float) Math.Sqrt(3)*width)/6),
                    new PointF(center.X + 0.5f*width, center.Y + ((float) Math.Sqrt(3)*width)/6),
                    new PointF(center.X, center.Y - ((float) Math.Sqrt(3)*width)/3)
                };
            graphics.FillPolygon(new SolidBrush(color), points2);
        }

        public static void DrawTriangle(this Graphics graphics, PointF center, float width, Color color)
        {
            PointF[] points2 =
                {
                    new PointF(center.X - 0.5f*width, center.Y + ((float) Math.Sqrt(3)*width)/6),
                    new PointF(center.X + 0.5f*width, center.Y + ((float) Math.Sqrt(3)*width)/6),
                    new PointF(center.X, center.Y - ((float) Math.Sqrt(3)*width)/3)
                };
            graphics.FillPolygon(new SolidBrush(color), points2);
        }

        public static void DrawTriangles(this Graphics graphics, IEnumerable<PointF> center, float width, Color color)
        {
            foreach(PointF point in center)
            {
                DrawTriangle(graphics, point, width, color);
            }
        }

        public static void DrawTriangles(this IGraphics graphics, IEnumerable<PointF> center, float width, Color color)
        {
            foreach (PointF point in center)
            {
                DrawTriangle(graphics, point, width, color);
            }
        }

        public static double DegreeToRadian(float angle)
        {
            return Math.PI * angle / 180.0f;
        }

        public static int MeasureDisplayStringWidth(this Graphics graphics, string text, Font font)
        {
            const int width = 32;

            Bitmap bitmap = new Bitmap(width, 1, graphics);
            SizeF size = graphics.MeasureString(text, font);
            Graphics anagra = Graphics.FromImage(bitmap);

            int measuredWidth = (int) size.Width;

            if (anagra != null)
            {
                anagra.Clear(Color.White);
                anagra.DrawString(text + "|", font, Brushes.Black,
                                  width - measuredWidth, -font.Height/2f);

                for (int i = width - 1; i >= 0; i--)
                {
                    measuredWidth--;
                    if (bitmap.GetPixel(i, 0).R != 255) // found a non-white pixel ?
                        break;
                }
            }

            return measuredWidth;
        }
    }
}
